﻿/**
@name: layer 弹窗
*/

/**弹窗类 */
let doms: string[] = ['layui-layer', '.layui-layer-title', '.layui-layer-main', '.layui-layer-dialog', 'layui-layer-iframe', 'layui-layer-content', 'layui-layer-btn', 'layui-layer-close'];
/**动画类 */
let anims: string[] = ['layer-anim-00', 'layer-anim-01', 'layer-anim-02', 'layer-anim-03', 'layer-anim-04', 'layer-anim-05', 'layer-anim-06'];

/**弹窗类别 */
export enum LayerMode {
    /**信息框 */
    dialog,
    /**页面层 */
    page,
    /**iframe层 */
    iframe,
    /**加载层 */
    loading,
    /**tips层 */
    tips
}

/**弹窗动画 */
export const enum LayerAnim {
    /**无 */
    none = -1,
    /**平滑放大 */
    boost = 0,
    /**从上掉落 */
    fall = 1,
    /**从最底部往上滑入 */
    rise = 2,
    /**从左滑入 */
    slide = 3,
    /**从左翻滚 */
    roll = 4,
    /**渐显 */
    fadeIn = 5,
    /**抖动 */
    shake = 6
}

/**tips定位 */
export const enum LayerTipsLocation {
    /**上 */
    top = 1,
    /**右 */
    right = 2,
    /**下 */
    bottom = 3,
    /**左 */
    left = 4
}

/**弹窗按钮 */
interface LayerButton {
    /**文本 */
    text?: string;
    /**css样式 */
    style?: string;
    /**单击回调 */
    click?: (index?: number, layero?: JQuery<HTMLElement>) => any;
}

/**弹窗配置 */
interface LayerOptions {
    /**
     * 基本层类型 类型：Number，默认：0
     * layer提供了5种层类型。可传入的值有：0（信息框，默认）1（页面层）2（iframe层）3（加载层）4（tips层）
     * */
    type?: LayerMode;
    /**
     * 标题 类型：String/Array/Boolean，默认：'信息'
     * title支持三种类型的值，若你传入的是普通的字符串，如title :'我是标题'，那么只会改变标题文本；若你还需要自定义标题区域样式，那么你可以title: ['文本', 'font-size:18px;']，数组第二项可以写任意css样式；如果你不想显示标题栏，你可以title: false
     * */
    title?: string | boolean | [string, string];
    /**
     * 内容 类型：String/DOM/Array，默认：''
     * content可传入的值是灵活多变的，不仅可以传入普通的html内容，还可以指定DOM，更可以随着type的不同而不同
     * */
    content?: string | JQuery<HTMLElement> | [string, string] | [string, HTMLElement];
    /**
     * 样式类名 类型：String，默认：''
     * skin不仅允许你传入layer内置的样式class名，还可以传入您自定义的class名。目前layer内置的skin有：layui-layer-lanlayui-layer-molv
     * */
    skin?: string;
    /**
     * 宽高 类型：String/Array，默认：'auto'
     * 在默认状态下，layer是宽高都自适应的，但当你只想定义宽度时，你可以area: '500px'，高度仍然是自适应的。当你宽高都要定义时，你可以area: ['500px', '300px']
     * */
    area?: string | [string, string];
    /**坐标 类型：String/Array，默认：垂直水平居中 */
    offset?: string | [string, string] | 't' | 'r' | 'b' | 'l' | 'lt' | 'lb' | 'rt' | 'rb';
    /**
     * 图标（信息框和加载层的私有参数）类型：Number，默认：-1（信息框）/0（加载层）
     * 信息框默认不显示图标。当你想显示图标时，默认皮肤可以传入0-6如果是加载层，可以传入0-2
     * */
    icon?: (-1) | 0 | 1 | 2 | 3 | 4 | 5 | 6;
    /**按钮 */
    btns?: LayerButton[];
    /**按钮排列 类型：String，默认：r */
    btnAlign?: 'l' | 'c' | 'r';
    /**关闭按钮 */
    closeBtn?: 0 | 1 | 2 | false;
    /**
     * 遮罩
     * 即弹层外区域。默认是0.3透明度的黑色背景（'#000'）。如果你想定义别的颜色，可以shade: [0.8, '#393D49']；如果你不想显示遮罩，可以shade: 0
     * */
    shade?: number | false | [number, string];
    /**是否点击遮罩关闭 类型：Boolean，默认：false */
    shadeClose?: boolean;
    /**
     * 自动关闭所需毫秒 类型：Number，默认：0
     * 默认不会自动关闭。当你想自动关闭时，可以time: 5000，即代表5秒后自动关闭，注意单位是毫秒（1秒=1000毫秒）
     * */
    time?: number;
    /**
     * 用于控制弹层唯一标识 类型：String，默认：空字符
     * 设置该值后，不管是什么类型的层，都只允许同时弹出一个。一般用于页面层和iframe层模式
     * */
    id?: string;
    /**弹出动画 */
    anim?: LayerAnim;
    /**
     * 关闭动画 类型：Boolean，默认：true
     * 默认情况下，关闭层时会有一个过度动画。如果你不想开启，设置 isOutAnim: false 即可
     * */
    isOutAnim?: boolean;
    /**
     * 最大最小化 类型：Boolean，默认：false
     * 该参数值对type:1和type:2有效。默认不显示最大小化按钮。需要显示配置maxmin: true即可
     * */
    maxmin?: boolean;
    /**
     * 固定 类型：Boolean，默认：true
     * 即鼠标滚动时，层是否固定在可视区域。如果不想，设置fixed: false即可
     * */
    fixed?: boolean;
    /**
     * 是否允许拉伸 类型：Boolean，默认：true
     * 默认情况下，你可以在弹层右下角拖动来拉伸尺寸。如果对指定的弹层屏蔽该功能，设置 false即可。该参数对loading、tips层无效
     * */
    resize?: boolean;
    /**
     * 监听窗口拉伸动作 类型：Function，默认：null
     * 当你拖拽弹层右下角对窗体进行尺寸调整时，如果你设定了该回调，则会执行。回调返回一个参数：当前层的DOM对象
     * */
    resizing?: (layero: JQuery<HTMLElement>) => any;
    /**是否允许浏览器出现滚动条 */
    scrollbar?: boolean;
    /**
     * 最大宽度 类型：Number，默认：360
     * 请注意：只有当area: 'auto'时，maxWidth的设定才有效
     * */
    maxWidth?: number;
    /**
     * 最大高度 类型：Number，默认：无
     * 请注意：只有当高度自适应时，maxHeight的设定才有效
     * */
    maxHeight?: number;
    /**
     * 层叠顺序 类型：Number，默认：19891014（贤心生日 0.0）
     * 一般用于解决和其它组件的层叠冲突
     * */
    zIndex?: number;
    /**
     * 触发拖动的元素 类型：String/DOM/Boolean，默认：'.layui-layer-title'
     * 默认是触发标题区域拖拽。如果你想单独定义，指向元素的选择器或者DOM即可。你还配置设定move: false来禁止拖拽
     * */
    move?: string | JQuery<HTMLElement> | false;
    /**是否允许拖拽到窗口外 类型：Boolean，默认：false */
    moveOut?: boolean;
    /**
     * 拖动完毕后的回调方法 类型：Function，默认：null
     * 默认不会触发moveEnd，如果你需要，设定moveEnd: function(layero){}即可。其中layero为当前层的DOM对象
     * */
    moveEnd?: (layero: JQuery<HTMLElement>) => any;
    /**
     * tips方向和颜色 类型：Number/Array，默认：2
     * tips层的私有参数。支持上右下左四个方向，通过1-4进行方向设定。如tips: 3则表示在元素的下面出现。有时你还可能会定义一些颜色，可以设定tips: [1, '#c00']
     * */
    tips?: LayerTipsLocation | [LayerTipsLocation, string | boolean];
    /**
     * 是否允许多个tips 类型：Boolean，默认：false
     * 允许多个意味着不会销毁之前的tips层。通过tipsMore: true开启
     * */
    tipsMore?: boolean;
    /**
     * 层弹出后的成功回调方法 类型：Function，默认：null
     * 当你需要在层创建完毕时即执行一些语句，可以通过该回调。success会携带两个参数，分别是当前层DOM当前层索引
     * */
    success?: (layero: JQuery<HTMLElement>, index?: number) => any;
    /**
     * 右上角关闭按钮触发的回调 类型：Function，默认：null
     * 该回调携带两个参数，分别为：当前层索引参数（index）、当前层的DOM对象（layero），默认会自动触发关闭。如果不想关闭，return false即可
     * */
    cancel?: (index: number, layero: JQuery<HTMLElement>) => any;
    /**
     * 层销毁后触发的回调 类型：Function，默认：null
     * 无论是确认还是取消，只要层被销毁了，end都会执行，不携带任何参数
     * */
    end?: () => any;
    /**最大化 */
    full?: (layero: JQuery<HTMLElement>) => any;
    /**最小化 */
    min?: (layero: JQuery<HTMLElement>) => any;
    /**还原 */
    restore?: (layero: JQuery<HTMLElement>) => any;
}

let $win: JQuery<Window>, $html: JQuery<HTMLElement>, ready: {
    path?: string;
    config?: LayerOptions & { path?: string };
    end?: object;
    minIndex?: number;
    minLeft?: number[];
    moveElem?: JQuery<HTMLElement>;
    btn?: string[];
    getStyle?: (node: HTMLElement, name: string) => any;
    link?: (href: string, fn?: () => any, cssname?: string) => void;
    /**主入口 */
    run?: () => void;
    /**for ie6 恢复select */
    reselect?: () => any;
    record?: (layero: JQuery<HTMLElement>) => void;
    rescollbar?: (index: number | string) => void;
} = {
    path: function () {
        let jsPath: string = document.currentScript ? (<any>document.currentScript).src : function () {
            let js = document.scripts, last = js.length - 1, src;
            for (let i = last; i > 0; i--) {
                if ((<any>js[i]).readyState === 'interactive') {
                    src = js[i].src;
                    break;
                }
            }
            return src || js[last].src;
        }();
        return jsPath.substring(0, jsPath.lastIndexOf('/') + 1);
    }(),
    config: {},
    end: {},
    minIndex: 0,
    minLeft: [],
    moveElem: $(`<div></div>`),
    btn: ['&#x786E;&#x5B9A;', '&#x53D6;&#x6D88;'],
    //获取节点的style属性值
    getStyle: function (node: HTMLElement, name: string) {
        let style: CSSStyleDeclaration = (<any>node).currentStyle ? (<any>node).currentStyle : window.getComputedStyle(node, null);
        return style[style.getPropertyValue ? 'getPropertyValue' : 'getAttribute'](name);
    },

    //载入CSS配件
    link: function (href: string, fn?: () => any, cssname?: string) {
        //未设置路径，则不主动加载css
        if (!layer.path) return;

        let head = document.getElementsByTagName("head")[0], link = document.createElement('link');
        if (typeof fn === 'string') cssname = fn;
        let app = (cssname || href).replace(/\.|\//g, '');
        let id = 'layuicss-' + app, timeout = 0;

        link.rel = 'stylesheet';
        link.href = layer.path + href;
        link.id = id;

        if (!document.getElementById(id)) {
            head.appendChild(link);
        }

        if (typeof fn !== 'function') return;

        //轮询css是否加载完毕
        (function poll() {
            if (++timeout > 8 * 1000 / 100) {
                return window.console && console.error('layer.css: Invalid');
            };
            parseInt(ready.getStyle(document.getElementById(id), 'width')) === 1989 ? fn() : setTimeout(poll, 100);
        }());
    }
};

/**信息框 */
interface Alert {
    /**
     * @param content 消息内容
     * @param yes 确认回调
     */
    (content: string, yes?: (index?: number, layero?: JQuery<HTMLElement>) => any): number;
    /**
     * @param content 消息内容
     * @param options 弹窗配置
     * @param yes 确认回调
     */
    (content: string, options?: LayerOptions, yes?: (index?: number, layero?: JQuery<HTMLElement>) => any): number;
}

/**询问框 */
interface Confirm {
    /**
     * @param content 确认内容
     * @param options 弹窗配置
     * @param yes 确认回调
     * @param cancel 取消回调
     */
    (content: string, options?: LayerOptions, yes?: (index?: number, layero?: JQuery<HTMLElement>) => any, cancel?: (index?: number, layero?: JQuery<HTMLElement>) => any): number;
    /**
     * @param content 确认内容
     * @param yes 确认回调
     * @param cancel 取消回调
     */
    (content: string, yes?: (index?: number, layero?: JQuery<HTMLElement>) => any, cancel?: (index?: number, layero?: JQuery<HTMLElement>) => any): number;
}

/**提示框 */
interface Msg {
    (content: string, options?: LayerOptions, end?: () => any): number;
    (content: string, end?: () => any): number;
}

/**输入层 */
interface Prompt {
    (options: PromptOptions, yes?: (value?: string, index?: number, prompt?: JQuery<HTMLElement>) => any): number;
    (yes?: (value?: string, index?: number, prompt?: JQuery<HTMLElement>) => any): number;
}

/**输入框类型 */
export const enum PromptFormType {
    /**文本 */
    text = 0,
    /**密码 */
    password = 1,
    /**多行文本 */
    area = 2
}

/**输入层选项 */
interface PromptOptions extends LayerOptions {
    /**输入框类型，支持0（文本）默认1（密码）2（多行文本） */
    formType?: PromptFormType;
    /**初始时的值，默认空字符 */
    value?: string;
    /**可输入文本的最大长度，默认500 */
    maxlength?: number;
}

/**tab层选项 */
interface TabOptions extends LayerOptions {
    tab?: { title?: string; content?: string; }[];
    change?: (index?: number) => any;
}

/**图片信息 */
interface Photos {
    /**相册标题 */
    title?: string;
    /**相册id */
    id?: number | string;
    /**初始显示的图片序号，默认0 */
    start?: number;
    /**相册包含的图片 */
    data?: {
        /**图片名 */
        alt?: string;
        /**图片id */
        pid?: number | string;
        /**原图地址 */
        src?: string;
        /**缩略图地址 */
        thumb?: string;
    }[];
}

/**相册层选项 */
interface PhotosOptions extends LayerOptions {
    /**图片标签 */
    img?: string;
    /**图片数据或父级元素 */
    photos?: string | Photos;
    /**切换回调 */
    tab?: (pic?, layero?: JQuery<HTMLElement>) => any;
}

interface Layer {
    /**版本号 */
    v?: string;
    /**ie版本 */
    ie?: boolean | string;
    /**显示层级 */
    zIndex?: number;
    /**索引 */
    index?: number;
    /**资源目录 */
    path?: string;
    /**初始化全局配置 */
    config?: (options?: LayerOptions & { extend?: string | [string] }, fn?: () => any) => this;
    /**初始化就绪 */
    ready?: (callback?: () => any) => this;
    /**配置缓存 */
    cache?: LayerOptions & { path?: string };
    /**打开弹窗 */
    open?: (options: LayerOptions) => number;
    /**信息框 */
    alert?: Alert;
    /**询问框 */
    confirm?: Confirm;
    /**提示框 */
    msg?: Msg;
    /**仿系统prompt */
    prompt?: Prompt;
    /**tab层 */
    tab?: (options?: TabOptions) => number;
    /**相册层 */
    photos?: (options: PhotosOptions, loop?: boolean, key?: boolean) => number;
    /**加载层 */
    load?: (icon: number, options?: LayerOptions) => number;
    /**tips层 */
    tips?: (content: string, follow: HTMLElement | string, options: LayerOptions) => number;
    /**置顶元素 */
    setTop?: (layero: JQuery<HTMLElement>) => number;
    /**获取子iframe的DOM */
    getChildFrame?: (selector: string, index: number | string) => JQuery<HTMLElement | Text | Comment | Document>;
    /**得到当前iframe层的索引，子iframe时使用 */
    getFrameIndex?: (name: string) => string;
    /**iframe层自适应宽高 */
    iframeAuto?: (index: number | string) => void;
    /**重置iframe url */
    iframeSrc?: (index: number | string, url: string) => void;
    /**设定层的样式 */
    style?: (index: number | string, options, limit?: boolean) => void;
    /**最小化 */
    min?: (index: number | string) => void;
    /**还原 */
    restore?: (index: number | string) => void;
    /**全屏 */
    full?: (index: number | string) => void;
    /**改变title */
    title?: (name: string, index: number | string) => void;
    /**关闭layer总方法 */
    close?: (index: number | string) => void;
    /**关闭所有层 */
    closeAll?: (type?: string) => void;
}

/**layer弹窗 */
let layer: Layer = {
    v: '3.1.1',
    ie: function () {
        let agent = navigator.userAgent.toLowerCase();
        return (!!(<any>window).ActiveXObject || "ActiveXObject" in window) ? (
            (agent.match(/msie\s(\d+)/) || [])[1] || '11' //由于ie11并没有msie的标识
        ) : false;
    }(),
    index: 100000,
    path: ready.path,
    config: function (options, fn) {
        options = options || {};
        layer.cache = ready.config = $.extend({}, ready.config, options);
        layer.path = ready.config.path || layer.path;
        typeof options.extend === 'string' && (options.extend = [options.extend]);

        if (ready.config.path) layer.ready();

        if (!options.extend) return this;

        ready.link('theme/' + options.extend);

        return this;
    },
    ready: function (callback?: () => any) {
        let cssname = 'layer', ver = '', path = 'theme/default/layer.css?v=' + layer.v + ver;
        ready.link(path, callback, cssname);
        return this;
    },

    alert: function (content: string, param0: LayerOptions | ((index?: number, layero?: JQuery<HTMLElement>) => any), param1: (index?: number, layero?: JQuery<HTMLElement>) => any) {
        let type = typeof param0 === 'function';
        if (type) param1 = param0 as ((index?: number, layero?: JQuery<HTMLElement>) => any);
        return layer.open($.extend({
            content: content,
            btns: [
                {
                    text: ready.btn[0],
                    click: param1
                }
            ]
        }, type ? {} : param0));
    } as Alert,

    confirm: function (content: string, param0, param1, param2) {
        let type = typeof param0 === 'function';
        if (type) {
            param2 = param1;
            param1 = param0;
        }
        return layer.open($.extend({
            content: content,
            btns: [
                {
                    text: ready.btn[0],
                    click: param1
                },
                {
                    text: ready.btn[1],
                    click: param2
                }
            ]
        }, type ? {} : param0));
    } as Confirm,

    msg: function (content: string, param0, param1) {
        let type = typeof param0 === 'function', rskin = ready.config.skin;
        let skin = (rskin ? rskin + ' ' + rskin + '-msg' : '') || 'layui-layer-msg';
        let anim = anims.length - 1;
        if (type) param1 = param0;
        return layer.open($.extend({
            content: content,
            time: 3000,
            shade: false,
            skin: skin,
            title: false,
            closeBtn: false,
            btn: false,
            resize: false,
            end: param1
        }, (type && !ready.config.skin) ? {
            skin: skin + ' layui-layer-hui',
            anim: anim
        } : function () {
            param0 = param0 || {};
            if (param0.icon === -1 || param0.icon === undefined && !ready.config.skin) {
                param0.skin = skin + ' ' + (param0.skin || 'layui-layer-hui');
            }
            return param0;
        }()));
    } as Msg,

    load: function (icon, options) {
        return layer.open($.extend({
            type: 3,
            icon: icon || 0,
            resize: false,
            shade: 0.01
        }, options));
    },

    tips: function (content, follow, options) {
        return layer.open($.extend({
            type: 4,
            content: [content, follow],
            closeBtn: false,
            time: 3000,
            shade: false,
            resize: false,
            fixed: false,
            maxWidth: 210
        }, options));
    }
};

class LayerClass {
    /**弹窗索引 */
    index: number;
    /**弹窗配置 */
    config: LayerOptions & { follow?: string | HTMLElement };
    /**窗体DOM对象 */
    layero: JQuery<HTMLElement>;

    constructor(options: LayerOptions) {
        this.config = {
            type: 0,
            shade: 0.3,
            fixed: true,
            move: doms[1],
            title: '&#x4FE1;&#x606F;',
            offset: 'auto',
            area: 'auto',
            closeBtn: 1,
            time: 0,
            zIndex: 19891014,
            maxWidth: 360,
            anim: 0,
            isOutAnim: true,
            icon: -1,
            resize: true,
            scrollbar: true,
            tips: 2
        };

        this.index = ++layer.index;
        this.config = $.extend({}, this.config, ready.config, options);

        let scope = this;
        document.body ? scope.create() : setTimeout(function () {
            scope.create();
        }, 30);
    }

    /**
     * 创建容器
     * @param conType 内容类别
     * @param callback 回调
     */
    vessel(conType: boolean, callback: (html: string[], titleHTML: string, moveElem: JQuery<HTMLElement>) => any) {
        let scope = this, times = scope.index, config = scope.config;
        let zIndex = config.zIndex + times, titype = typeof config.title === 'object';
        let ismax = config.maxmin && (config.type === 1 || config.type === 2);
        let titleHTML = (config.title ? '<div class="layui-layer-title" style="' + (titype ? config.title[1] : '') + '">'
            + (titype ? config.title[0] : config.title)
            + '</div>' : '');

        config.zIndex = zIndex;
        callback([
            //遮罩
            config.shade ? ('<div class="layui-layer-shade" id="layui-layer-shade' + times + '" times="' + times + '" style="' + ('z-index:' + (zIndex - 1) + '; ') + '"></div>') : '',

            //主体
            '<div class="' + doms[0] + (' layui-layer-' + LayerMode[config.type]) + (((config.type == 0 || config.type == 2) && !config.shade) ? ' layui-layer-border' : '') + ' ' + (config.skin || '') + '" id="' + doms[0] + times + '" type="' + LayerMode[config.type] + '" times="' + times + '" showtime="' + config.time + '" conType="' + (conType ? 'object' : 'string') + '" style="z-index: ' + zIndex + '; width:' + config.area[0] + ';height:' + config.area[1] + (config.fixed ? '' : ';position:absolute;') + '">'
            + (conType && config.type != 2 ? '' : titleHTML)
            + '<div id="' + (config.id || '') + '" class="layui-layer-content' + ((config.type == 0 && config.icon !== -1) ? ' layui-layer-padding' : '') + (config.type == 3 ? ' layui-layer-loading' + config.icon : '') + '">'
            + (config.type == 0 && config.icon !== -1 ? '<i class="layui-layer-ico layui-layer-ico' + config.icon + '"></i>' : '')
            + (config.type == 1 && conType ? '' : (config.content || ''))
            + '</div>'
            + '<span class="layui-layer-setwin">' + function () {
                let closebtn = ismax ? '<a class="layui-layer-min" href="javascript:;"><cite></cite></a><a class="layui-layer-ico layui-layer-max" href="javascript:;"></a>' : '';
                config.closeBtn && (closebtn += '<a class="layui-layer-ico ' + doms[7] + ' ' + doms[7] + (config.title ? config.closeBtn : (config.type == 4 ? '1' : '2')) + '" href="javascript:;"></a>');
                return closebtn;
            }() + '</span>'
            + (config.btns ? function () {
                let button = '';
                for (let i = 0, len = config.btns.length; i < len; i++) {
                    button += '<a class="' + doms[6] + '' + i + '">' + config.btns[i].text + '</a>'
                }
                return '<div class="' + doms[6] + ' layui-layer-btn-' + (config.btnAlign || '') + '">' + button + '</div>'
            }() : '')
            + (config.resize ? '<span class="layui-layer-resize"></span>' : '')
            + '</div>'
        ], titleHTML, $('<div class="layui-layer-move"></div>'));
        return scope;
    }

    /**创建骨架 */
    create() {
        let scope = this,
            config = scope.config,
            times = scope.index,
            nodeIndex, content = config.content, conType = typeof content === 'object',
            body = $('body');

        if (config.id && $('#' + config.id)[0]) return;

        if (typeof config.area === 'string') {
            config.area = config.area === 'auto' ? ['', ''] : [config.area, ''];
        }

        if (layer.ie == '6') {
            config.fixed = false;
        }

        switch (config.type) {
            case 0:
                config.btns = ('btns' in config) ? config.btns : [{ text: ready.btn[0] }];
                layer.closeAll('dialog');
                break;
            case 2:
                content = config.content = conType ? config.content : [(config.content as string) || 'http://layer.layui.com', 'auto'];
                config.content = '<iframe scrolling="' + (config.content[1] || 'auto') + '" allowtransparency="true" id="' + doms[4] + '' + times + '" name="' + doms[4] + '' + times + '" onload="this.className=\'\';" class="layui-layer-load" frameborder="0" src="' + config.content[0] + '"></iframe>';
                break;
            case 3:
                delete config.title;
                delete config.closeBtn;
                config.icon === -1 && (config.icon = 0);
                layer.closeAll('loading');
                break;
            case 4:
                conType || (config.content = [config.content as any, 'body']);
                config.follow = config.content[1];
                config.content = config.content[0] + '<i class="layui-layer-TipsG"></i>';
                delete config.title;
                config.tips = typeof config.tips === 'object' ? config.tips : [config.tips, true];
                config.tipsMore || layer.closeAll('tips');
                break;
        }

        //建立容器
        scope.vessel(conType, function (html, titleHTML, moveElem) {
            body.append(html[0]);
            conType ? function () {
                (config.type == 2 || config.type == 4) ? function () {
                    $('body').append(html[1]);
                }() : function () {
                    if (!(<JQuery<HTMLElement>>content).parents('.' + doms[0])[0]) {
                        (<JQuery<HTMLElement>>content).data('display', (<JQuery<HTMLElement>>content).css('display')).show().addClass('layui-layer-wrap').wrap(html[1]);
                        $('#' + doms[0] + times).find('.' + doms[5]).before(titleHTML);
                    }
                }();
            }() : body.append(html[1]);
            $('.layui-layer-move')[0] || body.append(ready.moveElem = moveElem);
            scope.layero = $('#' + doms[0] + times);
            config.scrollbar || $html.css('overflow', 'hidden').attr('layer-full', times);
        }).auto(times);

        //遮罩
        $('#layui-layer-shade' + scope.index).css({
            'background-color': config.shade[1] || '#000'
            , 'opacity': config.shade[0] || config.shade
        });

        config.type == 2 && layer.ie == '6' && scope.layero.find('iframe').attr('src', content[0] as string);

        //坐标自适应浏览器窗口尺寸
        config.type == 4 ? scope.tips() : scope.offset();
        if (config.fixed) {
            $win.on('resize', function () {
                scope.offset();
                (/^\d+%$/.test(config.area[0]) || /^\d+%$/.test(config.area[1])) && scope.auto(times);
                config.type == 4 && scope.tips();
            });
        }

        config.time <= 0 || setTimeout(function () {
            layer.close(scope.index)
        }, config.time);
        scope.move().callback();

        //为兼容jQuery3.0的css动画影响元素尺寸计算
        if (anims[config.anim]) {
            let animClass = 'layer-anim ' + anims[config.anim];
            scope.layero.addClass(animClass).one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function () {
                $(this).removeClass(animClass);
            });
        };

        //记录关闭动画
        if (config.isOutAnim) {
            scope.layero.data('isOutAnim', true);
        }
    }

    /**自适应 */
    auto(index) {
        let scope = this, config = scope.config, layero = $('#' + doms[0] + index);

        if (config.area[0] === '' && config.maxWidth > 0) {
            //为了修复IE7下一个让人难以理解的bug
            if (layer.ie && Number(layer.ie) < 8 && config.btns) {
                layero.width(layero.innerWidth());
            }
            layero.outerWidth() > config.maxWidth && layero.width(config.maxWidth);
        }

        let area = [layero.innerWidth(), layero.innerHeight()],
            titHeight = layero.find(doms[1]).outerHeight() || 0,
            btnHeight = layero.find('.' + doms[6]).outerHeight() || 0,
            setHeight = function (elem) {
                elem = layero.find(elem);
                elem.height(area[1] - titHeight - btnHeight - 2 * (parseFloat(elem.css('padding-top')) | 0));
            };

        switch (config.type) {
            case 2:
                setHeight('iframe');
                break;
            default:
                if (config.area[1] === '') {
                    if (config.maxHeight > 0 && layero.outerHeight() > config.maxHeight) {
                        area[1] = config.maxHeight;
                        setHeight('.' + doms[5]);
                    } else if (config.fixed && area[1] >= $win.height()) {
                        area[1] = $win.height();
                        setHeight('.' + doms[5]);
                    }
                } else {
                    setHeight('.' + doms[5]);
                }
                break;
        };

        return scope;
    }

    /**垂直定位 */
    offsetTop: number | string;
    /**水平定位 */
    offsetLeft: number | string;

    /**计算坐标 */
    offset() {
        let scope = this, config = scope.config, layero = scope.layero;
        let area = [layero.outerWidth(), layero.outerHeight()];
        let type = typeof config.offset === 'object';
        scope.offsetTop = ($win.height() - area[1]) / 2;
        scope.offsetLeft = ($win.width() - area[0]) / 2;

        if (type) {
            scope.offsetTop = config.offset[0];
            scope.offsetLeft = config.offset[1] || scope.offsetLeft;
        } else if (config.offset !== 'auto') {

            if (config.offset === 't') { //上
                scope.offsetTop = 0;
            } else if (config.offset === 'r') { //右
                scope.offsetLeft = $win.width() - area[0];
            } else if (config.offset === 'b') { //下
                scope.offsetTop = $win.height() - area[1];
            } else if (config.offset === 'l') { //左
                scope.offsetLeft = 0;
            } else if (config.offset === 'lt') { //左上角
                scope.offsetTop = 0;
                scope.offsetLeft = 0;
            } else if (config.offset === 'lb') { //左下角
                scope.offsetTop = $win.height() - area[1];
                scope.offsetLeft = 0;
            } else if (config.offset === 'rt') { //右上角
                scope.offsetTop = 0;
                scope.offsetLeft = $win.width() - area[0];
            } else if (config.offset === 'rb') { //右下角
                scope.offsetTop = $win.height() - area[1];
                scope.offsetLeft = $win.width() - area[0];
            } else {
                scope.offsetTop = config.offset as string;
            }

        }

        if (!config.fixed) {
            scope.offsetTop = /%$/.test(scope.offsetTop as string) ?
                $win.height() * parseFloat(scope.offsetTop as string) / 100
                : parseFloat(scope.offsetTop as string);
            scope.offsetLeft = /%$/.test(scope.offsetLeft as string) ?
                $win.width() * parseFloat(scope.offsetLeft as string) / 100
                : parseFloat(scope.offsetLeft as string);
            scope.offsetTop += $win.scrollTop();
            scope.offsetLeft += $win.scrollLeft();
        }

        if (layero.attr('minLeft')) {
            scope.offsetTop = $win.height() - (layero.find(doms[1]).outerHeight() || 0);
            scope.offsetLeft = layero.css('left');
        }

        layero.css({ top: scope.offsetTop, left: scope.offsetLeft });
    }

    tips() {
        let that = this, config = that.config, layero = that.layero;
        let layArea = [layero.outerWidth(), layero.outerHeight()], follow = $(config.follow as any);
        if (!follow[0]) follow = $('body');
        let goal: {
            width?: number;
            height?: number;
            top?: number;
            left?: number;
            autoLeft?: () => void;
            tipLeft?: number;
            tipTop?: number;
            where?: (() => void)[];
        } = {
            width: follow.outerWidth(),
            height: follow.outerHeight(),
            top: follow.offset().top,
            left: follow.offset().left
        }, tipsG = layero.find('.layui-layer-TipsG');

        let guide = config.tips[0];
        config.tips[1] || tipsG.remove();

        goal.autoLeft = function () {
            if (goal.left + layArea[0] - $win.width() > 0) {
                goal.tipLeft = goal.left + goal.width - layArea[0];
                tipsG.css({ right: 12, left: 'auto' });
            } else {
                goal.tipLeft = goal.left;
            };
        }

        //辨别tips的方位
        goal.where = [function () { //上        
            goal.autoLeft();
            goal.tipTop = goal.top - layArea[1] - 10;
            tipsG.removeClass('layui-layer-TipsB').addClass('layui-layer-TipsT').css('border-right-color', config.tips[1]);
        }, function () { //右
            goal.tipLeft = goal.left + goal.width + 10;
            goal.tipTop = goal.top;
            tipsG.removeClass('layui-layer-TipsL').addClass('layui-layer-TipsR').css('border-bottom-color', config.tips[1]);
        }, function () { //下
            goal.autoLeft();
            goal.tipTop = goal.top + goal.height + 10;
            tipsG.removeClass('layui-layer-TipsT').addClass('layui-layer-TipsB').css('border-right-color', config.tips[1]);
        }, function () { //左
            goal.tipLeft = goal.left - layArea[0] - 10;
            goal.tipTop = goal.top;
            tipsG.removeClass('layui-layer-TipsR').addClass('layui-layer-TipsL').css('border-bottom-color', config.tips[1]);
        }];
        goal.where[guide - 1]();

        /* 8*2为小三角形占据的空间 */
        if (guide === 1) {
            goal.top - ($win.scrollTop() + layArea[1] + 8 * 2) < 0 && goal.where[2]();
        } else if (guide === 2) {
            $win.width() - (goal.left + goal.width + layArea[0] + 8 * 2) > 0 || goal.where[3]()
        } else if (guide === 3) {
            (goal.top - $win.scrollTop() + goal.height + layArea[1] + 8 * 2) - $win.height() > 0 && goal.where[0]();
        } else if (guide === 4) {
            layArea[0] + 8 * 2 - goal.left > 0 && goal.where[1]()
        }

        layero.find('.' + doms[5]).css({
            'background-color': config.tips[1],
            'padding-right': (config.closeBtn ? '30px' : '')
        });
        layero.css({
            left: goal.tipLeft - (config.fixed ? $win.scrollLeft() : 0),
            top: goal.tipTop - (config.fixed ? $win.scrollTop() : 0)
        });
    }

    /**拖拽层 */
    move(): this {
        let scope = this, config = scope.config, _DOC = $(document), layero = scope.layero,
            moveElem = layero.find(config.move as string), resizeElem = layero.find('.layui-layer-resize'),
            dict: any = {};

        if (config.move) {
            moveElem.css('cursor', 'move');
        }

        moveElem.on('mousedown', function (e) {
            e.preventDefault();
            if (config.move) {
                dict.moveStart = true;
                dict.offset = [
                    e.clientX - parseFloat(layero.css('left'))
                    , e.clientY - parseFloat(layero.css('top'))
                ];
                ready.moveElem.css('cursor', 'move').show();
            }
        });

        resizeElem.on('mousedown', function (e) {
            e.preventDefault();
            dict.resizeStart = true;
            dict.offset = [e.clientX, e.clientY];
            dict.area = [
                layero.outerWidth(),
                layero.outerHeight()
            ];
            ready.moveElem.css('cursor', 'se-resize').show();
        });

        _DOC.on('mousemove', function (e) {
            //拖拽移动
            if (dict.moveStart) {
                let X = e.clientX - dict.offset[0], Y = e.clientY - dict.offset[1], fixed = layero.css('position') === 'fixed';

                e.preventDefault();

                dict.stX = fixed ? 0 : $win.scrollLeft();
                dict.stY = fixed ? 0 : $win.scrollTop();

                //控制元素不被拖出窗口外
                if (!config.moveOut) {
                    let setRig = $win.width() - layero.outerWidth() + dict.stX
                        , setBot = $win.height() - layero.outerHeight() + dict.stY;
                    X < dict.stX && (X = dict.stX);
                    X > setRig && (X = setRig);
                    Y < dict.stY && (Y = dict.stY);
                    Y > setBot && (Y = setBot);
                }

                layero.css({ left: X, top: Y });
            }

            //Resize
            if (config.resize && dict.resizeStart) {
                let X = e.clientX - dict.offset[0], Y = e.clientY - dict.offset[1];

                e.preventDefault();

                layer.style(scope.index, { width: dict.area[0] + X, height: dict.area[1] + Y })
                dict.isResize = true;
                config.resizing && config.resizing(layero);
            }
        }).on('mouseup', function (e) {
            if (dict.moveStart) {
                delete dict.moveStart;
                ready.moveElem.hide();
                config.moveEnd && config.moveEnd(layero);
            }
            if (dict.resizeStart) {
                delete dict.resizeStart;
                ready.moveElem.hide();
            }
        });

        return scope;
    }

    callback() {
        let scope = this, layero = scope.layero, config = scope.config;
        scope.openLayer();
        if (config.success) {
            if (config.type == 2) {
                layero.find('iframe').on('load', function () {
                    config.success(layero, scope.index);
                });
            } else {
                config.success(layero, scope.index);
            }
        }
        layer.ie == '6' && scope.IE6(layero);

        //按钮
        layero.find('.' + doms[6]).children('a').on('click', function () {
            let index = $(this).index();
            let close = config.btns[index].click && config.btns[index].click(scope.index, layero);
            close === false || layer.close(scope.index);
        });

        //取消
        function cancel() {
            let close = config.cancel && config.cancel(scope.index, layero);
            close === false || layer.close(scope.index);
        }

        //右上角关闭回调
        layero.find('.' + doms[7]).on('click', cancel);

        //点遮罩关闭
        if (config.shadeClose) {
            $('#layui-layer-shade' + scope.index).on('click', function () {
                layer.close(scope.index);
            });
        }

        //最小化
        layero.find('.layui-layer-min').on('click', function () {
            let min = config.min && config.min(layero);
            min === false || layer.min(scope.index);
        });

        //全屏/还原
        layero.find('.layui-layer-max').on('click', function () {
            if ($(this).hasClass('layui-layer-maxmin')) {
                layer.restore(scope.index);
                config.restore && config.restore(layero);
            } else {
                layer.full(scope.index);
                setTimeout(function () {
                    config.full && config.full(layero);
                }, 100);
            }
        });

        config.end && (ready.end[scope.index] = config.end);
    }

    IE6(layero?: JQuery<HTMLElement>) {
        //隐藏select
        $('select').each(function (index, value) {
            let sthis = $(this);
            if (!sthis.parents('.' + doms[0])[0]) {
                sthis.css('display') === 'none' || sthis.attr({ 'layer': '1' }).hide();
            }
            sthis = null;
        });
    }

    /**需依赖原型的对外方法 */
    openLayer() {
        let scope = this;

        //置顶当前窗口
        layer.zIndex = scope.config.zIndex;
        layer.setTop = function (layero) {
            let setZindex = function () {
                layer.zIndex++;
                layero.css('z-index', layer.zIndex + 1);
            };
            layer.zIndex = parseInt(layero[0].style.zIndex);
            layero.on('mousedown', setZindex);
            return layer.zIndex;
        };
    }
}

ready.reselect = function () {
    $.each($('select'), function (index, value) {
        let sthis = $(this);
        if (!sthis.parents('.' + doms[0])[0]) {
            (sthis.attr('layer') == '1' && $('.' + doms[0]).length < 1) && sthis.removeAttr('layer').show();
        }
        sthis = null;
    });
};

ready.record = function (layero) {
    let area = [
        layero.width(),
        layero.height(),
        layero.position().top,
        layero.position().left + parseFloat(layero.css('margin-left'))
    ];
    layero.find('.layui-layer-max').addClass('layui-layer-maxmin');
    layero.attr({ area: area });
};

ready.rescollbar = function (index) {
    if ($html.attr('layer-full') == index) {
        if ($html[0].style.removeProperty) {
            $html[0].style.removeProperty('overflow');
        } else {
            (<any>$html[0].style).removeAttribute('overflow');
        }
        $html.removeAttr('layer-full');
    }
};

/**内置成员 */
(<any>window).layer = layer;

layer.getChildFrame = function (selector, index) {
    index = index || $('.' + doms[4]).attr('times');
    return $('#' + doms[0] + index).find('iframe').contents().find(selector);
};

layer.getFrameIndex = function (name) {
    return $('#' + name).parents('.' + doms[4]).attr('times');
};

layer.iframeAuto = function (index) {
    if (!index) return;
    let heg = layer.getChildFrame('html', index).outerHeight();
    let layero = $('#' + doms[0] + index);
    let titHeight = layero.find(doms[1]).outerHeight() || 0;
    let btnHeight = layero.find('.' + doms[6]).outerHeight() || 0;
    layero.css({ height: heg + titHeight + btnHeight });
    layero.find('iframe').css({ height: heg });
};

layer.iframeSrc = function (index, url) {
    $('#' + doms[0] + index).find('iframe').attr('src', url);
};

layer.style = function (index, options, limit) {
    let layero = $('#' + doms[0] + index),
        contElem = layero.find('.layui-layer-content'),
        type = layero.attr('type'),
        titHeight = layero.find(doms[1]).outerHeight() || 0,
        btnHeight = layero.find('.' + doms[6]).outerHeight() || 0,
        minLeft = layero.attr('minLeft');

    if (type === LayerMode[3] || type === LayerMode[4]) {
        return;
    }

    if (!limit) {
        if (parseFloat(options.width) <= 260) {
            options.width = 260;
        };

        if (parseFloat(options.height) - titHeight - btnHeight <= 64) {
            options.height = 64 + titHeight + btnHeight;
        };
    }

    layero.css(options);
    btnHeight = layero.find('.' + doms[6]).outerHeight();

    if (type === LayerMode[2]) {
        layero.find('iframe').css({
            height: parseFloat(options.height) - titHeight - btnHeight
        });
    } else {
        contElem.css({
            height: parseFloat(options.height) - titHeight - btnHeight
                - parseFloat(contElem.css('padding-top'))
                - parseFloat(contElem.css('padding-bottom'))
        })
    }
};

layer.min = function (index) {
    let layero = $('#' + doms[0] + index),
        titHeight = layero.find(doms[1]).outerHeight() || 0,
        left = layero.attr('minLeft') || (181 * ready.minIndex) + 'px',
        position = layero.css('position');

    ready.record(layero);

    if (ready.minLeft[0]) {
        left = ready.minLeft[0] as any;
        ready.minLeft.shift();
    }

    layero.attr('position', position);

    layer.style(index, {
        width: 180
        , height: titHeight
        , left: left
        , top: $win.height() - titHeight
        , position: 'fixed'
        , overflow: 'hidden'
    }, true);

    layero.find('.layui-layer-min').hide();
    layero.attr('type') === 'page' && layero.find(doms[4]).hide();
    ready.rescollbar(index);

    if (!layero.attr('minLeft')) {
        ready.minIndex++;
    }
    layero.attr('minLeft', left);
};

layer.restore = function (index) {
    let layero = $('#' + doms[0] + index), area = layero.attr('area').split(',');
    let type = layero.attr('type');
    layer.style(index, {
        width: parseFloat(area[0]),
        height: parseFloat(area[1]),
        top: parseFloat(area[2]),
        left: parseFloat(area[3]),
        position: layero.attr('position'),
        overflow: 'visible'
    }, true);
    layero.find('.layui-layer-max').removeClass('layui-layer-maxmin');
    layero.find('.layui-layer-min').show();
    layero.attr('type') === 'page' && layero.find(doms[4]).show();
    ready.rescollbar(index);
};

layer.full = function (index) {
    let layero = $('#' + doms[0] + index), timer;
    ready.record(layero);
    if (!$html.attr('layer-full')) {
        $html.css('overflow', 'hidden').attr('layer-full', index);
    }
    clearTimeout(timer);
    timer = setTimeout(function () {
        let isfix = layero.css('position') === 'fixed';
        layer.style(index, {
            top: isfix ? 0 : $win.scrollTop(),
            left: isfix ? 0 : $win.scrollLeft(),
            width: $win.width(),
            height: $win.height()
        }, true);
        layero.find('.layui-layer-min').hide();
    }, 100);
};

layer.title = function (name, index) {
    let title = $('#' + doms[0] + (index || layer.index)).find(doms[1]);
    title.html(name);
};

layer.close = function (index) {
    let layero = $('#' + doms[0] + index), type = layero.attr('type'), closeAnim = 'layer-anim-close';
    if (!layero[0]) return;
    let WRAP = 'layui-layer-wrap', remove = function () {
        if (type === LayerMode[1] && layero.attr('conType') === 'object') {
            layero.children(':not(.' + doms[5] + ')').remove();
            let wrap = layero.find('.' + WRAP);
            for (let i = 0; i < 2; i++) {
                wrap.unwrap();
            }
            wrap.css('display', wrap.data('display')).removeClass(WRAP);
        } else {
            //低版本IE 回收 iframe
            if (type === LayerMode[2]) {
                try {
                    let iframe = $('#' + doms[4] + index)[0];
                    (<any>iframe).contentWindow.document.write('');
                    (<any>iframe).contentWindow.close();
                    layero.find('.' + doms[5])[0].removeChild(iframe);
                } catch (e) { }
            }
            layero[0].innerHTML = '';
            layero.remove();
        }
        typeof ready.end[index] === 'function' && ready.end[index]();
        delete ready.end[index];
    };

    if (layero.data('isOutAnim')) {
        layero.addClass('layer-anim ' + closeAnim);
    }

    $('#layui-layer-moves, #layui-layer-shade' + index).remove();
    layer.ie == '6' && ready.reselect();
    ready.rescollbar(index);
    if (layero.attr('minLeft')) {
        ready.minIndex--;
        ready.minLeft.push(Number(layero.attr('minLeft')));
    }

    if ((layer.ie && Number(layer.ie) < 10) || !layero.data('isOutAnim')) {
        remove()
    } else {
        setTimeout(function () {
            remove();
        }, 200);
    }
};

layer.closeAll = function (type) {
    $.each($('.' + doms[0]), function () {
        let othis = $(this);
        let is = type ? (othis.attr('type') === type) : 1;
        is && layer.close(othis.attr('times'));
        is = null;
    });
};

/** 

  拓展模块，layui开始合并在一起

 */

let cache = layer.cache || {}, skin = function (type: string) {
    return (cache.skin ? (' ' + cache.skin + ' ' + cache.skin + '-' + type) : '');
};

//输入层
layer.prompt = function (options?: PromptOptions | ((value?: string, index?: number, prompt?: JQuery<HTMLElement>) => any), yes?: (value?: string, index?: number, prompt?: JQuery<HTMLElement>) => any) {
    let style = '';
    options = options || {};

    if (typeof options === 'function') yes = options;

    if ((<PromptOptions>options).area) {
        let area = (<PromptOptions>options).area;
        style = 'style="width: ' + area[0] + '; height: ' + area[1] + ';"';
        delete (<PromptOptions>options).area;
    }
    let prompt, content = (<PromptOptions>options).formType == 2 ? '<textarea class="layui-layer-input"' + style + '>' + ((<PromptOptions>options).value || '') + '</textarea>' : function () {
        return '<input type="' + ((<PromptOptions>options).formType == 1 ? 'password' : 'text') + '" class="layui-layer-input" value="' + ((<PromptOptions>options).value || '') + '">';
    }();

    let success = (<PromptOptions>options).success;
    delete (<PromptOptions>options).success;

    return layer.open($.extend({
        type: 1
        , btn: ['&#x786E;&#x5B9A;', '&#x53D6;&#x6D88;']
        , content: content
        , skin: 'layui-layer-prompt' + skin('prompt')
        , maxWidth: $win.width()
        , success: function (layero) {
            prompt = layero.find('.layui-layer-input');
            prompt.focus();
            typeof success === 'function' && success(layero);
        }
        , resize: false
        , yes: function (index) {
            let value = prompt.val();
            if (value === '') {
                prompt.focus();
            } else if (value.length > ((<PromptOptions>options).maxlength || 500)) {
                layer.tips('&#x6700;&#x591A;&#x8F93;&#x5165;' + ((<PromptOptions>options).maxlength || 500) + '&#x4E2A;&#x5B57;&#x6570;', prompt, { tips: 1 });
            } else {
                yes && yes(value, index, prompt);
            }
        }
    }, options as LayerOptions));
};

//tab层
layer.tab = function (options) {
    options = options || {};

    let tab = options.tab || [], THIS = 'layui-this', success = options.success;

    delete options.success;

    return layer.open($.extend({
        type: 1,
        skin: 'layui-layer-tab' + skin('tab'),
        resize: false,
        title: function () {
            let len = tab.length, ii = 1, str = '';
            if (len > 0) {
                str = '<span class="' + THIS + '">' + tab[0].title + '</span>';
                for (; ii < len; ii++) {
                    str += '<span>' + tab[ii].title + '</span>';
                }
            }
            return str;
        }(),
        content: '<ul class="layui-layer-tabmain">' + function () {
            let len = tab.length, ii = 1, str = '';
            if (len > 0) {
                str = '<li class="layui-layer-tabli ' + THIS + '">' + (tab[0].content || 'no content') + '</li>';
                for (; ii < len; ii++) {
                    str += '<li class="layui-layer-tabli">' + (tab[ii].content || 'no  content') + '</li>';
                }
            }
            return str;
        }() + '</ul>',
        success: function (layero) {
            let btn = layero.find('.layui-layer-title').children();
            let main = layero.find('.layui-layer-tabmain').children();
            btn.on('mousedown', function (e) {
                e.stopPropagation ? e.stopPropagation() : e.cancelBubble = true;
                let othis = $(this), index = othis.index();
                othis.addClass(THIS).siblings().removeClass(THIS);
                main.eq(index).show().siblings().hide();
                typeof options.change === 'function' && options.change(index);
            });
            typeof success === 'function' && success(layero);
        }
    }, options));
};

//相册层
layer.photos = function (options, loop, key) {
    let dict: any = {};
    options = options || {};
    if (!options.photos) return;
    let type = options.photos.constructor === Object;
    let photos: Photos = type ? options.photos as Photos : {}, data = photos.data || [];
    let start = photos.start || 0;
    dict.imgIndex = (start | 0) + 1;

    options.img = options.img || 'img';

    let success = options.success;
    delete options.success;

    if (!type) { //页面直接获取
        let parent = $(options.photos as string), pushData = function () {
            data = [];
            parent.find(options.img).each(function (index) {
                let othis = $(this);
                othis.attr('layer-index', index);
                data.push({
                    alt: othis.attr('alt'),
                    pid: othis.attr('layer-pid'),
                    src: othis.attr('layer-src') || othis.attr('src'),
                    thumb: othis.attr('src')
                });
            })
        };

        pushData();

        if (data.length === 0) return;

        loop || parent.on('click', options.img, function () {
            let othis = $(this), index = othis.attr('layer-index');
            layer.photos($.extend(options, {
                photos: {
                    start: index,
                    data: data,
                    tab: options.tab
                },
                full: options.full
            }), true);
            pushData();
        })

        //不直接弹出
        if (!loop) return;

    } else if (data.length === 0) {
        return layer.msg('&#x6CA1;&#x6709;&#x56FE;&#x7247;');
    }

    //上一张
    dict.imgprev = function (key) {
        dict.imgIndex--;
        if (dict.imgIndex < 1) {
            dict.imgIndex = data.length;
        }
        dict.tabimg(key);
    };

    //下一张
    dict.imgnext = function (key, errorMsg) {
        dict.imgIndex++;
        if (dict.imgIndex > data.length) {
            dict.imgIndex = 1;
            if (errorMsg) { return };
        }
        dict.tabimg(key)
    };

    //方向键
    dict.keyup = function (event) {
        if (!dict.end) {
            let code = event.keyCode;
            event.preventDefault();
            if (code === 37) {
                dict.imgprev(true);
            } else if (code === 39) {
                dict.imgnext(true);
            } else if (code === 27) {
                layer.close(dict.index);
            }
        }
    }

    //切换
    dict.tabimg = function (key) {
        if (data.length <= 1) return;
        photos.start = dict.imgIndex - 1;
        layer.close(dict.index);
        return layer.photos(options, true, key);
        setTimeout(function () {
            layer.photos(options, true, key);
        }, 200);
    }

    //一些动作
    dict.event = function () {
        dict.bigimg.hover(function () {
            dict.imgsee.show();
        }, function () {
            dict.imgsee.hide();
        });

        dict.bigimg.find('.layui-layer-imgprev').on('click', function (event) {
            event.preventDefault();
            dict.imgprev();
        });

        dict.bigimg.find('.layui-layer-imgnext').on('click', function (event) {
            event.preventDefault();
            dict.imgnext();
        });

        $(document).on('keyup', dict.keyup);
    };

    //图片预加载
    function loadImage(url, callback, error) {
        let img = new Image();
        img.src = url;
        if (img.complete) {
            return callback(img);
        }
        img.onload = function () {
            img.onload = null;
            callback(img);
        };
        img.onerror = function (e) {
            img.onerror = null;
            error(e);
        };
    };

    dict.loadi = layer.load(1, {
        shade: 'shade' in options ? false : 0.9,
        scrollbar: false
    });

    loadImage(data[start].src, function (img) {
        layer.close(dict.loadi);
        dict.index = layer.open($.extend({
            type: 1,
            id: 'layui-layer-photos',
            area: function () {
                let imgarea = [img.width, img.height];
                let winarea = [$(window).width() - 100, $(window).height() - 100];

                //如果 实际图片的宽或者高比 屏幕大（那么进行缩放）
                if (!options.full && (imgarea[0] > winarea[0] || imgarea[1] > winarea[1])) {
                    let wh = [imgarea[0] / winarea[0], imgarea[1] / winarea[1]];//取宽度缩放比例、高度缩放比例
                    if (wh[0] > wh[1]) {//取缩放比例最大的进行缩放
                        imgarea[0] = imgarea[0] / wh[0];
                        imgarea[1] = imgarea[1] / wh[0];
                    } else if (wh[0] < wh[1]) {
                        imgarea[0] = imgarea[0] / wh[1];
                        imgarea[1] = imgarea[1] / wh[1];
                    }
                }

                return [imgarea[0] + 'px', imgarea[1] + 'px'];
            }(),
            title: false,
            shade: 0.9,
            shadeClose: true,
            closeBtn: false,
            move: '.layui-layer-phimg img',
            moveType: 1,
            scrollbar: false,
            moveOut: true,
            //anim: Math.random()*5|0,
            isOutAnim: false,
            skin: 'layui-layer-photos' + skin('photos'),
            content: '<div class="layui-layer-phimg">'
                + '<img src="' + data[start].src + '" alt="' + (data[start].alt || '') + '" layer-pid="' + data[start].pid + '">'
                + '<div class="layui-layer-imgsee">'
                + (data.length > 1 ? '<span class="layui-layer-imguide"><a href="javascript:;" class="layui-layer-iconext layui-layer-imgprev"></a><a href="javascript:;" class="layui-layer-iconext layui-layer-imgnext"></a></span>' : '')
                + '<div class="layui-layer-imgbar" style="display:' + (key ? 'block' : '') + '"><span class="layui-layer-imgtit"><a href="javascript:;">' + (data[start].alt || '') + '</a><em>' + dict.imgIndex + '/' + data.length + '</em></span></div>'
                + '</div>'
                + '</div>',
            success: function (layero, index) {
                dict.bigimg = layero.find('.layui-layer-phimg');
                dict.imgsee = layero.find('.layui-layer-imguide,.layui-layer-imgbar');
                dict.event(layero);
                options.tab && options.tab(data[start], layero);
                typeof success === 'function' && success(layero);
            }, end: function () {
                dict.end = true;
                $(document).off('keyup', dict.keyup);
            }
        }, options));
    }, function () {
        layer.close(dict.loadi);
        layer.msg('&#x5F53;&#x524D;&#x56FE;&#x7247;&#x5730;&#x5740;&#x5F02;&#x5E38;<br>&#x662F;&#x5426;&#x7EE7;&#x7EED;&#x67E5;&#x770B;&#x4E0B;&#x4E00;&#x5F20;&#xFF1F;', {
            time: 30000,
            btns: [
                {
                    text: '&#x4E0B;&#x4E00;&#x5F20;',
                    click: function () {
                        data.length > 1 && dict.imgnext(true, true);
                    }
                },
                {
                    text: '&#x4E0D;&#x770B;&#x4E86;'
                }
            ]
        });
    });
};

ready.run = function () {
    $win = $(window);
    $html = $('html');
    layer.open = function (deliver) {
        let o = new LayerClass(deliver);
        return o.index;
    };
};

//加载方式
(function () { //普通script标签加载
    ready.run();
    layer.ready();
})();

export default layer;